package whendone

/**
  implicit definition to make Projects and Entries available for SBinary serialization.
  @author Henrik Huttunen
*/
object ProjectBinary{
  import sbinary._
  import sbinary.Instances._
  import Project._

  /** Binary is formed lazily */
  def lazyBinary[T](binary: =>Binary[T]) = new Binary[T]{
    lazy val handle = binary
    def reads(stream: java.io.DataInput) = handle.reads(stream)
    def writes(t: T)(stream: java.io.DataOutput) = handle.writes(t)(stream)
  }
  /** Composes project from name, subprojects, log entries, and attributes. */
  def composeProject(name: String, subProjects: List[Project], entries: List[Entry], attributes: List[String]) = { 
    val project = new Project(None, name) // parent must be set after the load phase
    for(subProject <- subProjects) project.addProject(subProject)
    for(entry <- entries) project.addEntry(entry)
    for(attribute <- attributes) project.addAttribute(attribute)
    project
  }
  /** Decomposes project to name, subprojects, log entries and attributes. */
  val decomposeProject = {(proj: Project) => (proj.name, proj.projects, proj.entries, proj.attributes)}
  val composeEntry = {(description: String, time: Long) => new Entry(description, new java.util.Date(time))}
  val decomposeEntry = {(entry: Entry) => (entry.description, entry.date.getTime)}

  /** Entry is a Binary, for serialization */
  implicit val entryIsBinary: Binary[Entry] = generic.Generic.asProduct2(composeEntry)(decomposeEntry)
  
  /** Project is a Binary, for serialization */
  implicit val projectIsBinary: Binary[Project] = lazyBinary[Project]{
    generic.Generic.asProduct4(composeProject _)(decomposeProject)
  }
}
